package com.nf.sms.dao.impl;

import com.nf.sms.dao.ProductDao;
import com.nf.sms.entity.Product;
import com.nf.sms.utils.DbUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * ProductDao接口的实现类
 *
 * @author ZQX
 * @date 2024-10-12
 */
public class ProductDaoImpl implements ProductDao {
    @Override
    public List<Product> selectByPage(int currentPage, int pageCount) {
        // 定义一个集合，用于存储查询的数据
        List<Product> list = new ArrayList<>();

        // 第一：定义要操作数据库的 SQL 语句，参数使用 ? 占位符代替
        StringBuilder sb = new StringBuilder();
        sb.append("select * from (");
        sb.append("select *,");
        sb.append("row_number() over(order by t1.product_id asc) as rownumber");
        sb.append(" from product as t1");
        sb.append(") as t2");
        sb.append(" where rownumber between ? and ?");

        // String sql = sb.toString();

        // 第二：获取连接对象
        Connection conn = DbUtil.getConnection();
        PreparedStatement psmt = null;
        ResultSet rst = null;

        try {
            // 第三：预编译 SQL 语句 - 获取语句对象
            psmt = conn.prepareStatement(sb.toString());

            // 第四：给占位符填充数据 - 注：Xxx代表是数据类型
            // 语句对象.setXxx(参数索引,值)
            psmt.setInt(1, (currentPage - 1) * pageCount + 1);
            psmt.setInt(2, currentPage * pageCount);


            // 第五：执行 SQL 语句 - executeUpdate()、executeQuery()
            // 语法一：int 变量 = 语句对象.executeUpdate()
            // 语法二：ResultSet 变量 = 语句对象.executeQuery()
            rst = psmt.executeQuery();

            // 第六：对结果进行处理 - 把结果集中的数据读取出来，并存储到实体对象中
            // 结果集对象.next() ： 判断是否存在下一条数据
            // 语法一：结果集对象.getXxx(查询字段的下标索引) : 获取某个字段的数据
            // 语法二：结果集对象.getXxx(查询字段的名称) : 获取某个字段的数据
            // 1.判断是否存在查询数据
            while (rst.next()) {
                // 2.读取当前行的各列数据
                String productId = rst.getString(1);
                String productName = rst.getString(2);
                String productType = rst.getString(3);
                float productPrice = rst.getFloat(4);
                int productCount = rst.getInt(5);
                String productImage = rst.getString(6);
                Date productDate = rst.getDate(7);
                String productDesc = rst.getString(8);
                int productSale = rst.getInt(9);
                int productStatus = rst.getInt(10);


                // 3.实例化实体对象 - 一个商品表示的就一行数据
                Product p = new Product();

                // 4.把各列数据封装到实体对象中
                p.setProductId(productId);
                p.setProductName(productName);
                p.setProductDate(productDate);
                p.setProductDesc(productDesc);
                p.setProductCount(productCount);
                p.setProductImage(productImage);
                p.setProductPrice(productPrice);
                p.setProductStatus(productStatus);
                p.setProductType(productType);
                p.setProductSale(productSale);

                // 5.把各行（商品）的数据添加到List集合中
                list.add(p);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 第七：关闭对象
            DbUtil.close(rst, psmt, conn);
        }

        return list;
    }

    @Override
    public long selectCount() {
        long r = 0;

        // 第一：定义要操作数据库SQL语句
        String sql = "select count(product_id) from product";

        // 第二：获取连接对象
        Connection conn = DbUtil.getConnection();
        PreparedStatement psmt = null;
        ResultSet rst = null;

        try {
            // 第三：预编译 SQL 语句 - 获取语句对象
            psmt = conn.prepareStatement(sql);

            // 第四：给占位符填充数据 - 注：Xxx代表是数据类型
            // 语句对象.setXxx(参数索引,值)

            // 第五：执行 SQL 语句 - executeUpdate()、executeQuery()
            // 语法一：int 变量 = 语句对象.executeUpdate()
            // 语法二：ResultSet 变量 = 语句对象.executeQuery()
            rst = psmt.executeQuery();

            // 第六：对结果进行处理 - 把结果集中的数据读取出来，并存储到实体对象中
            // 结果集对象.next() ： 判断是否存在下一条数据
            // 语法一：结果集对象.getXxx(查询字段的下标索引) : 获取某个字段的数据
            // 语法二：结果集对象.getXxx(查询字段的名称) : 获取某个字段的数据
            // 判断是否存在查询数据
            if (rst.next()) {
                r = rst.getInt(1);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 第七：关闭对象
            DbUtil.close(rst, psmt, conn);
        }

        return r;
    }

    @Override
    public List<Product> selectByPage(int currentPage, int pageCount, String cond) {
        // 定义一个集合，用于存储查询的数据
        List<Product> list = new ArrayList<>();

        // 第一：定义要操作数据库的 SQL 语句，参数使用 ? 占位符代替
        StringBuilder sb = new StringBuilder();

        sb.append("select * from (");
        sb.append("select *,");
        sb.append("row_number() over(order by t1.product_id asc) as rownumber ");
        sb.append("from product as t1 where product_name like ?");
        sb.append(") as t2 ");
        sb.append("where rownumber between ? and ?");

        // 第二：获取连接对象
        Connection conn = DbUtil.getConnection();
        PreparedStatement psmt = null;
        ResultSet rst = null;

        try {
            // 第三：预编译 SQL 语句 - 获取语句对象
            psmt = conn.prepareStatement(sb.toString());

            // 第四：给占位符填充数据 - 注：Xxx代表是数据类型
            // 语句对象.setXxx(参数索引,值)
            psmt.setString(1, '%' + cond + '%');
            psmt.setInt(2, (currentPage - 1) * pageCount + 1);
            psmt.setInt(3, currentPage * pageCount);


            // 第五：执行 SQL 语句 - executeUpdate()、executeQuery()
            // 语法一：int 变量 = 语句对象.executeUpdate()
            // 语法二：ResultSet 变量 = 语句对象.executeQuery()
            rst = psmt.executeQuery();

            // 第六：对结果进行处理 - 把结果集中的数据读取出来，并存储到实体对象中
            // 结果集对象.next() ： 判断是否存在下一条数据
            // 语法一：结果集对象.getXxx(查询字段的下标索引) : 获取某个字段的数据
            // 语法二：结果集对象.getXxx(查询字段的名称) : 获取某个字段的数据
            // 1.判断是否存在查询数据
            while (rst.next()) {
                // 2.读取当前行的各列数据
                String productId = rst.getString(1);
                String productName = rst.getString(2);
                String productType = rst.getString(3);
                float productPrice = rst.getFloat(4);
                int productCount = rst.getInt(5);
                String productImage = rst.getString(6);
                Date productDate = rst.getDate(7);
                String productDesc = rst.getString(8);
                int productSale = rst.getInt(9);
                int productStatus = rst.getInt(10);


                // 3.实例化实体对象 - 一个商品表示的就一行数据
                Product p = new Product();

                // 4.把各列数据封装到实体对象中
                p.setProductId(productId);
                p.setProductName(productName);
                p.setProductDate(productDate);
                p.setProductDesc(productDesc);
                p.setProductCount(productCount);
                p.setProductImage(productImage);
                p.setProductPrice(productPrice);
                p.setProductStatus(productStatus);
                p.setProductType(productType);
                p.setProductSale(productSale);

                // 5.把各行（商品）的数据添加到List集合中
                list.add(p);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 第七：关闭对象
            DbUtil.close(rst, psmt, conn);
        }

        return list;
    }

    @Override
    public long selectCount(String cond) {
        long r = 0;

        // 第一：定义要操作数据库SQL语句
        String sql = "select count(product_id) from product where product_name like ?";

        // 第二：获取连接对象
        Connection conn = DbUtil.getConnection();
        PreparedStatement psmt = null;
        ResultSet rst = null;

        try {
            // 第三：预编译 SQL 语句 - 获取语句对象
            psmt = conn.prepareStatement(sql);

            // 第四：给占位符填充数据 - 注：Xxx代表是数据类型
            // 语句对象.setXxx(参数索引,值)
            psmt.setString(1, '%' + cond + '%');

            // 第五：执行 SQL 语句 - executeUpdate()、executeQuery()
            // 语法一：int 变量 = 语句对象.executeUpdate()
            // 语法二：ResultSet 变量 = 语句对象.executeQuery()
            rst = psmt.executeQuery();

            // 第六：对结果进行处理 - 把结果集中的数据读取出来，并存储到实体对象中
            // 结果集对象.next() ： 判断是否存在下一条数据
            // 语法一：结果集对象.getXxx(查询字段的下标索引) : 获取某个字段的数据
            // 语法二：结果集对象.getXxx(查询字段的名称) : 获取某个字段的数据
            // 判断是否存在查询数据
            if (rst.next()) {
                r = rst.getInt(1);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 第七：关闭对象
            DbUtil.close(rst, psmt, conn);
        }

        return r;
    }

    @Override
    public List<Product> selectByPage(int currentPage, int pageCount, Product product) {
        // 定义一个集合，用于存储查询的数据
        List<Product> list = new ArrayList<>();

        // 第一：定义要操作数据库的 SQL 语句，参数使用 ? 占位符代替
        StringBuilder sb = new StringBuilder();

        sb.append("select * from (");
        sb.append("select *, row_number() over(order by t1.product_id asc) as rownumber ");
        sb.append("from product as t1 ");
        sb.append("where 1=1 ");

        // 1. 定义 List 集合，用于存储查询条件 - Object是所有对象的父类
        List<Object> paramList = new ArrayList<>();

        // 2.动态拼接 SQL 语句
        if (product.getProductName() != null && !"".equals(product.getProductName().trim())) {
            sb.append("and product_name like ? ");
            paramList.add('%' + product.getProductName() + '%');
        }

        if (product.getProductType() != null && !"".equals(product.getProductType().trim())) {
            sb.append("and product_type=? ");
            paramList.add(product.getProductType());
        }
        sb.append(") as t2 ");
        sb.append("where rownumber between ? and ?");

        // 第二：获取连接对象
        Connection conn = DbUtil.getConnection();
        PreparedStatement psmt = null;
        ResultSet rst = null;

        try {
            // 第三：预编译 SQL 语句 - 获取语句对象
            psmt = conn.prepareStatement(sb.toString());

            // 第四：给占位符填充数据 - 注：Xxx代表是数据类型
            // 语句对象.setXxx(参数索引,值)
            for (int i = 0; i < paramList.size(); i++) {
                psmt.setObject(i + 1, paramList.get(i));
            }

            psmt.setInt(paramList.size() + 1, (currentPage - 1) * pageCount + 1);
            psmt.setInt(paramList.size() + 2, currentPage * pageCount);


            // 第五：执行 SQL 语句 - executeUpdate()、executeQuery()
            // 语法一：int 变量 = 语句对象.executeUpdate()
            // 语法二：ResultSet 变量 = 语句对象.executeQuery()
            rst = psmt.executeQuery();

            // 第六：对结果进行处理 - 把结果集中的数据读取出来，并存储到实体对象中
            // 结果集对象.next() ： 判断是否存在下一条数据
            // 语法一：结果集对象.getXxx(查询字段的下标索引) : 获取某个字段的数据
            // 语法二：结果集对象.getXxx(查询字段的名称) : 获取某个字段的数据
            // 1.判断是否存在查询数据
            while (rst.next()) {
                // 2.读取当前行的各列数据
                String productId = rst.getString(1);
                String productName = rst.getString(2);
                String productType = rst.getString(3);
                float productPrice = rst.getFloat(4);
                int productCount = rst.getInt(5);
                String productImage = rst.getString(6);
                Date productDate = rst.getDate(7);
                String productDesc = rst.getString(8);
                int productSale = rst.getInt(9);
                int productStatus = rst.getInt(10);


                // 3.实例化实体对象 - 一个商品表示的就一行数据
                Product p = new Product();

                // 4.把各列数据封装到实体对象中
                p.setProductId(productId);
                p.setProductName(productName);
                p.setProductDate(productDate);
                p.setProductDesc(productDesc);
                p.setProductCount(productCount);
                p.setProductImage(productImage);
                p.setProductPrice(productPrice);
                p.setProductStatus(productStatus);
                p.setProductType(productType);
                p.setProductSale(productSale);

                // 5.把各行（商品）的数据添加到List集合中
                list.add(p);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 第七：关闭对象
            DbUtil.close(rst, psmt, conn);
        }

        return list;
    }

    @Override
    public long selectCount(Product product) {
        long r = 0;

        // 第一：定义要操作数据库SQL语句
        StringBuilder sb = new StringBuilder("select count(product_id) from product where 1=1");

        // 1.定义 List 集合，用于存储查询条件 - Object是所有对象的父类
        List<Object> list = new ArrayList<>();

        // 2.动态拼接 SQL 语句
        if (product.getProductName() != null && !"".equals(product.getProductName().trim())) {
            sb.append("and product_name like ?");
            list.add('%' + product.getProductName() + '%');
        }

        if (product.getProductType() != null && !"".equals(product.getProductType().trim())) {
            sb.append("and product_type=?");
            list.add(product.getProductType());
        }


        // 第二：获取连接对象
        Connection conn = DbUtil.getConnection();
        PreparedStatement psmt = null;
        ResultSet rst = null;

        try {
            // 第三：预编译 SQL 语句 - 获取语句对象
            psmt = conn.prepareStatement(sb.toString());

            // 第四：给占位符填充数据 - 注：Xxx代表是数据类型
            // 语句对象.setXxx(参数索引,值)
            for (int i = 0; i < list.size(); i++) {
                psmt.setObject(i + 1, list.get(i));
            }

            // 第五：执行 SQL 语句 - executeUpdate()、executeQuery()
            // 语法一：int 变量 = 语句对象.executeUpdate()
            // 语法二：ResultSet 变量 = 语句对象.executeQuery()
            rst = psmt.executeQuery();

            // 第六：对结果进行处理 - 把结果集中的数据读取出来，并存储到实体对象中
            // 结果集对象.next() ： 判断是否存在下一条数据
            // 语法一：结果集对象.getXxx(查询字段的下标索引) : 获取某个字段的数据
            // 语法二：结果集对象.getXxx(查询字段的名称) : 获取某个字段的数据
            // 判断是否存在查询数据
            if (rst.next()) {
                r = rst.getInt(1);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 第七：关闭对象
            DbUtil.close(rst, psmt, conn);
        }

        return r;
    }
}
